<template>
  <div ref="appContainer" class="app-container home-bg-padding">
    <CustomSearch
      ref="searchForm"
      show-all.sync="false"
      :show-switch-icon="false"
      @search="searchFn"
      @reset="resetFn"
    >
      <template #btns>
        <sec-button
          v-if="permissions(AddRole)"
          type="primary"
          @click="handleAddRole"
          >添加角色</sec-button
        >
      </template>
    </CustomSearch>

    <div class="query-table">
      <sec-table
        v-loading="loading"
        :data="rolesList"
        style="width: 100%; height: calc(100% - 42px); overflow-y: scroll"
        size="mini"
        stripe
      >
        <sec-table-column align="center" label="角色标识" width="220">
          <template slot-scope="scope">{{ scope.row.roleCode }}</template>
        </sec-table-column>
        <sec-table-column align="center" label="角色名称" width="220">
          <template slot-scope="scope">{{ scope.row.roleName }}</template>
        </sec-table-column>
        <sec-table-column align="header-center" label="角色描述">
          <template slot-scope="scope">{{ scope.row.roleDesc }}</template>
        </sec-table-column>
        <sec-table-column align="header-center" label="创建时间">
          <template slot-scope="scope">{{ scope.row.createTime }}</template>
        </sec-table-column>
        <sec-table-column align="center" label="操作" width="230">
          <template slot-scope="scope">
            <sec-button
              type="text"
              size="small"
              icon="sec-icon-bianji"
              @click="handlePreview(scope)"
              >查看</sec-button
            >
            <sec-button
              v-if="permissions(EditRole)"
              type="text"
              size="small"
              icon="sec-icon-bianji"
              @click="handleEdit(scope)"
              >编辑</sec-button
            >
            <sec-button
              v-if="permissions(PermRole)"
              type="text"
              size="small"
              icon="el-icon-plus"
              @click="fetchTree(scope)"
              >权限</sec-button
            >
            <sec-button
              v-if="permissions(DeleteRole)"
              type="text"
              size="small"
              icon="el-icon-delete"
              @click="handleDelete(scope)"
              >删除</sec-button
            >
          </template>
        </sec-table-column>
      </sec-table>
      <div class="pagination">
        <sec-pagination
          :current-page.sync="pagination.pageNo"
          :page-size="pagination.pageSize"
          layout="total,prev, pager, next,sizes"
          :total="pagination.totalCount"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        ></sec-pagination>
      </div>
    </div>
    <!-- 查看 -->
    <sec-dialog
      :visible.sync="dialogPreviewVisible"
      :close-on-click-modal="false"
      title="查看角色"
    >
      <div class="preview-table">
        <table>
          <tr>
            <td>
              <span>角色名称:</span>
            </td>
            <td>{{ role.roleName }}</td>
          </tr>
          <tr>
            <td>
              <span>角色标识:</span>
            </td>
            <td>{{ role.roleCode }}</td>
          </tr>
          <tr>
            <td>
              <span>角色描述:</span>
            </td>
            <td>{{ role.roleDesc }}</td>
          </tr>
          <tr>
            <td>
              <span>创建时间:</span>
            </td>
            <td>{{ role.createTime }}</td>
          </tr>
        </table>
      </div>
    </sec-dialog>
    <!--  -->
    <sec-dialog
      v-if="dialogVisible"
      :visible.sync="dialogVisible"
      :title="dialogType === 'edit' ? '编辑角色' : '添加角色'"
      :close-on-click-modal="false"
    >
      <sec-form
        ref="formEle"
        :model="role"
        :rules="rules"
        labsec-width="80px"
        labsec-position="left"
      >
        <sec-form-item label="角色名称" prop="roleName">
          <sec-input
            v-model="role.roleName"
            size="medium"
            placeholder="Role Name"
            prop="roleName"
          />
        </sec-form-item>
        <sec-form-item label="角色标识" prop="roleCode">
          <sec-input
            v-model="role.roleCode"
            size="medium"
            placeholder="Role Code"
            :disabled="dialogType === 'edit'"
          />
        </sec-form-item>
        <sec-form-item label="角色描述" prop="roleDesc">
          <sec-input
            v-model="role.roleDesc"
            size="medium"
            placeholder="Role Description"
          />
        </sec-form-item>
      </sec-form>
      <div style="text-align: right">
        <sec-button type="danger" @click="dialogVisible = false">
          取消
        </sec-button>
        <sec-button type="primary" @click="confirmRole">确认</sec-button>
      </div>
    </sec-dialog>
    <!-- 角色树 -->
    <sec-dialog
      v-if="dialogTreeVisible"
      :visible.sync="dialogTreeVisible"
      title="权限分配"
      :close-on-click-modal="false"
    >
      <sec-tree
        ref="tree"
        v-loading="treeLoad"
        :data="menuTree"
        check-strictly
        show-checkbox
        node-key="id"
        default-expand-all
        :default-checked-keys="menuTreeCheck"
        :props="defaultProps"
        @check-change="checkChange"
      ></sec-tree>
      <div style="text-align: right">
        <sec-button type="danger" @click="dialogTreeVisible = false">
          取消
        </sec-button>
        <sec-button type="primary" @click="confirmRoleMenu">确认</sec-button>
      </div>
    </sec-dialog>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import { DeleteRole, AddRole, EditRole, PermRole } from '@/const/permissions'
import path from 'path'
import { deepClone } from '@/utils/util'
import http from '@/utils/http'
import pagination from '@/utils/mixins/pagination'
import { CustomSearch } from '@/components'
const defaultRole = {
  createTime: '2022-01-14 15:51:42',
  delFlag: '0',
  roleCode: '',
  roleDesc: '',
  roleId: '1',
  roleName: '',
  updateBy: null,
  updateTime: '2022-01-14 15:51:42'
}

export default {
  components: {
    CustomSearch
  },
  mixins: [pagination],
  data() {
    return {
      DeleteRole,
      AddRole,
      EditRole,
      PermRole,
      menuTree: [],
      menuTreeCheck: [],
      dialogTreeVisible: false,
      role: Object.assign({}, defaultRole),
      routes: [],
      rolesList: [],
      dialogVisible: false,
      dialogPreviewVisible: false,
      dialogType: 'new',
      checkStrictly: false,
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      rules: {
        roleCode: {
          required: true,
          message: '请输入角色标识',
          trigger: 'blur'
        },
        roleName: {
          required: true,
          message: '请输入角色名称',
          trigger: 'blur'
        },
        roleDesc: {
          required: true,
          message: '请输入角色描述',
          trigger: 'blur'
        }
      },
      loading: false,
      treeLoad: false,
      focusRole: {}
    }
  },
  computed: {
    routesData() {
      return this.routes
    },
    ...mapGetters(['permissions'])
  },
  watch: {
    currentPage: function (val) {
      this.getList()
    },
    pageSize: function (val) {
      this.getList()
    }
  },
  created() {
    // this.getRoutes()
    this.getList()
  },
  methods: {
    checkChange(node, checked, childrenChecked) {
      // 当当前节点被选中时，父节点默认选中
      if (checked) {
        this.$refs.tree.setChecked(node.parentId, true)
      }
    },
    async getRoutes() {
      const res = await http.getRoutes()
      this.serviceRoutes = res.data
      this.routes = this.generateRoutes(res.data)
    },
    async getList() {
      this.loading = true
      const { data } = await http.getRoleInfoList({
        pageNo: 1,
        pageSize: this.pagination.pageSize
      })
      const { rows, totalRows, pageNo, pageSize } = data
      this.rolesList = rows
      this.pagination = {
        ...this.pagination,
        pageNo,
        pageSize,
        totalCount: totalRows
      }
      this.loading = false
    },

    // Reshape the routes structure so that it looks the same as the sidebar
    generateRoutes(routes, basePath = '/') {
      const res = []

      for (let route of routes) {
        // skip some route
        if (route.hidden) {
          continue
        }

        const onlyOneShowingChild = this.onlyOneShowingChild(
          route.children,
          route
        )

        if (route.children && onlyOneShowingChild && !route.alwaysShow) {
          route = onlyOneShowingChild
        }

        const data = {
          path: path.resolve(basePath, route.path),
          title: route.meta && route.meta.title
        }

        // recursive child routes
        if (route.children) {
          data.children = this.generateRoutes(route.children, data.path)
        }
        res.push(data)
      }
      return res
    },
    generateArr(routes) {
      let data = []
      routes.forEach((route) => {
        data.push(route)
        if (route.children) {
          const temp = this.generateArr(route.children)
          if (temp.length > 0) {
            data = [...data, ...temp]
          }
        }
      })
      return data
    },
    handleAddRole() {
      this.role = Object.assign({}, defaultRole)
      this.dialogType = 'new'
      this.dialogVisible = true
    },
    handlePreview(scope) {
      this.dialogType = 'add'
      this.dialogPreviewVisible = true
      this.role = deepClone(scope.row)
    },
    async fetchTree({ row }) {
      this.focusRole = row
      this.dialogTreeVisible = true
      this.treeLoad = true
      const res = await http.getMenuTree()
      this.menuTree = res.data

      this.menuTreeCheck = []
      const { data } = await http.getMenuTreeStatus({ roleId: row.roleId })

      this.treeLoad = false
      this.menuTreeCheck = data
    },
    handleEdit(scope) {
      this.dialogType = 'edit'
      this.dialogVisible = true
      this.checkStrictly = true
      this.role = deepClone(scope.row)
    },
    handleDelete({ $index, row }) {
      this.$confirm('您确认要删除该角色?', '提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        closeOnClickModal: false,
        type: 'warning'
      })
        .then(async () => {
          await http.deleteRole({ roleId: row.roleId, roleName: row.roleName })
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          await this.getList()
        })
        .catch((err) => {
          console.error(err)
        })
    },
    generateTree(routes, basePath = '/', checkedKeys) {
      const res = []

      for (const route of routes) {
        const routePath = path.resolve(basePath, route.path)

        // recursive child routes
        if (route.children) {
          route.children = this.generateTree(
            route.children,
            routePath,
            checkedKeys
          )
        }

        if (
          checkedKeys.includes(routePath) ||
          (route.children && route.children.length >= 1)
        ) {
          res.push(route)
        }
      }
      return res
    },
    async confirmRoleMenu() {
      this.dialogTreeVisible = false
      const checkedKeys = this.$refs.tree.getCheckedKeys()
      console.log(checkedKeys)

      const res = await http.updateRoleMenu({
        menuIds: checkedKeys.join(','),
        roleId: this.focusRole.roleId
      })

      if (res.code === '200') {
        this.$message({
          type: 'success',
          message: '修改成功!'
        })
      } else {
        this.$message({
          type: 'error',
          message: '修改失败!'
        })
      }
    },
    async confirmRole() {
      this.$refs.formEle.validate(async (valid) => {
        if (valid) {
          const isEdit = this.dialogType === 'edit'

          if (isEdit) {
            await http.updateRole(this.role)
          } else {
            await http.addRole({
              roleCode: this.role.roleCode,
              roleDesc: this.role.roleDesc,
              roleName: this.role.roleName
            })
            // this.role.roleCode = data.roleCode
            this.rolesList.push(this.role)
          }

          const { roleDesc, roleCode, roleName } = this.role

          this.dialogVisible = false
          this.$notify({
            title: '完成',
            dangerouslyUseHTMLString: true,
            message: `
            <div>角色标识: ${roleCode}</div>
            <div>角色名称: ${roleName}</div>
            <div>角色描述: ${roleDesc}</div>
          `,
            type: 'success'
          })
          await this.getList()
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // reference: src/view/layout/components/Sidebar/SidebarItem.vue
    onlyOneShowingChild(children = [], parent) {
      let onlyOneChild = null
      const showingChildren = children.filter((item) => !item.hidden)

      // When there is only one child route, the child route is displayed by default
      if (showingChildren.length === 1) {
        onlyOneChild = showingChildren[0]
        onlyOneChild.path = path.resolve(parent.path, onlyOneChild.path)
        return onlyOneChild
      }

      // Show parent if there are no child route to display
      if (showingChildren.length === 0) {
        onlyOneChild = { ...parent, path: '', noShowingChildren: true }
        return onlyOneChild
      }

      return false
    }
  }
}
</script>

<style lang="scss" scoped>
.roles-table {
  margin-top: 30px;
}
.permission-tree {
  margin-bottom: 30px;
}
.line {
  padding: 10px 0;
  &.btn {
    padding-top: 0;
  }
  &.page {
    text-align: right;
  }
}
.preview-table {
  span {
    padding: 5px 16px 5px 0px;
    font-size: 14px;
    line-height: 1.5;
    color: #878585;
  }
}
.query-table {
  padding: 8px;
  background: #fff;
  flex: 1;
  height: 1%;
  .operate {
    font-size: 12px;
  }
  .idot {
    width: 8px;
    height: 8px;
    background: #19be6b;
    border-radius: 50%;
    display: inline-block;
    margin-right: 5px;
  }
  .sec-icon-bangzhu1 {
    margin-left: 3px;
    color: rgb(45, 140, 240);
  }
  .pagination {
    text-align: right;
    padding-top: 8px;
    .el-pagination {
      padding-right: 0;
    }
    .el-pagination__sizes {
      margin: 0;
    }
    .el-pagination .el-pagination__sizes .el-select .el-input {
      margin-right: 0;
    }
  }
  .el-table {
    .el-table-column--selection {
      .cell {
        padding-left: 14px;
      }
    }
    .el-table__body {
      width: 100%;
      // 使表格兼容safari，不错位
      table-layout: fixed !important;
    }
  }
}
.item {
  width: 30px;
}
</style>
